package com.platform.boot.config;

import com.platform.boot.security.ReactiveSecurityHelper;
import jakarta.validation.constraints.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.session.CookieWebSessionIdResolver;
import org.springframework.web.server.session.HeaderWebSessionIdResolver;
import org.springframework.web.server.session.WebSessionIdResolver;

import java.util.Collections;
import java.util.List;

/**
 * @author <a href="https://github.com/vnobo">Alex bob</a>
 */
@Configuration(proxyBeanMethods = false)
public class SessionConfiguration {

    @Bean
    public WebSessionIdResolver webSessionIdResolver() {
        HeaderWebSessionIdResolver resolver = new CustomHeaderWebSessionIdResolver();
        resolver.setHeaderName(ReactiveSecurityHelper.SECURITY_AUTH_TOKEN_HEADER);
        return resolver;
    }
    static class CustomHeaderWebSessionIdResolver extends HeaderWebSessionIdResolver {
        private final String xRequestedWith = "X-Requested-With";
        private final String xmlHttpRequest = "XMLHttpRequest";
        private final CookieWebSessionIdResolver cookieWebSessionIdResolver =
                new CookieWebSessionIdResolver();

        @Override
        public void setSessionId(ServerWebExchange exchange, @NonNull String id) {
            List<String> requestedWith =
                    exchange.getRequest().getHeaders().getOrDefault(xRequestedWith, Collections.emptyList());
            if (requestedWith.contains(xmlHttpRequest)) {
                super.setSessionId(exchange, id);
            } else {
                cookieWebSessionIdResolver.setSessionId(exchange, id);
            }
        }

        @Override
        public List<String> resolveSessionIds(@NotNull ServerWebExchange exchange) {
            List<String> requestedWith =
                    exchange.getRequest().getHeaders().getOrDefault(xRequestedWith, Collections.emptyList());
            if (requestedWith.contains(xmlHttpRequest)) {
                return super.resolveSessionIds(exchange);
            }
            return cookieWebSessionIdResolver.resolveSessionIds(exchange);
        }

        @Override
        public void expireSession(ServerWebExchange exchange) {
            List<String> requestedWith =
                    exchange.getRequest().getHeaders().getOrDefault(xRequestedWith, Collections.emptyList());
            if (requestedWith.contains(xmlHttpRequest)) {
                super.expireSession(exchange);
            } else {
                cookieWebSessionIdResolver.expireSession(exchange);
            }
        }
    }
}